# To change this template, choose Tools | Templates
# and open the template in the editor.

from game.object.world.io.world_reader_mysql import *
from game.object.world.io.world_writer_mysql import *
from game.object.world.io.world_generator import *
from game.object.world.cell import *

from threading import Thread

class WriteThread(Thread):
    def __init__(self, reader, cell):
        Thread.__init__(self)
        self.reader = reader
        self.cell = cell

    def run(self):
        self.cell.state = "loading"
        self.reader.load_cell(self.cell)
        self.cell.state = "valid"

class ReadThread(Thread):
    def __init__(self, reader, cell):
        Thread.__init__(self)
        self.reader = reader
        self.cell = cell

    def run(self):
        self.cell.state = "loading"
        self.reader.load_cell(self.cell)
        self.cell.state = "valid"

class GenerateThread(Thread):
    def __init__(self, gen, writer, cell):
        Thread.__init__(self)
        self.gen = gen
        self.writer = writer
        self.cell = cell

    def run(self):
        self.cell.state = "loading"
        self.gen.gen_cell(self.cell)
        self.cell.state = "valid"
        t = WriteThread(self.writer, self.cell)


class WorldManager:

    def __init__(self):
        self.reader = WorldReaderMySQL()
        self.writer = WorldWriterMySQL()
        self.generator = WorldGenerator()

        #The number of cells surrounding the active cell to retrieve data for
        self.radius = 2

        self.active_cell = None
        self.loaded_cells = {}


    def retrieve_cell(self, coord):
        """
        This will attempt to retrieve the details of the cell at the world
        coordinate of coord, which should be a 3-element tuple (x, y, z).
        If the cell has not been created, it will be generated and entered
        into the world data before retrieval
        """

        #create a key to access the cell
        ind = "{0}_{1}_{2}".format(coord[0], coord[1], coord[2])

        #if the key already exists in the cells in memory, retrieve from that
        if ind in self.loaded_cells:
            c = self.loaded_cells[ind]
            #if the cell exists, but is not valid, cannot return it
            if c.state != "valid":
                return None
            else:
                return c

        #try to load the cell from the data source
        if self.reader.cell_exists(coord):
            c = Cell()
            self.loaded_cells[ind] = c
            t = ReadThread(self.reader, c)
            t.start()
            return None
        #otherwise, do a generation for the cell
        else:
            c = Cell()
            self.loaded_cells[ind] = c
            t = GenerateThread(self.generator, self.reader, c)
            t.start()
            return None

    def drop_cell(self, cell):
        """
        This will write any data to the cell at the given coordinate to the
        datasource and then remove all references to the cell
        """
        self.writer.write_cell(cell.world_coord, cell)

    def change_active_cell(self, coord):
        if self.active_cell is not None:
            p_coord = self.active_cell.world_coord


